module Retro
   use HTypes
   use sysutils
   use OptimisationTypes
   use equations
   use objfunction
   implicit none
   
contains


subroutine OnInitiateRetro(Opt)
   implicit none
   type(TOptimisation), intent(inout) :: Opt
   open(cRetroFMeanFile, file = GetWorkFileName(Opt, Opt%IndexInput%OutFiles(roRetroFMean)), &
      action = 'write', status =  'replace')
   write(cRetroFMeanFile, "(A)") '#Retro F mean file   '   
   write(cRetroFMeanFile, "(A)") "Run id: " // lrtrim(Opt%RunId)
   write(cRetroFMeanFile, "(A)") 'One line contains: Iteration number and Mean F over years'   
   close(cRetroFMeanFile);
   open(cRetroSSBFile, file = GetWorkFileName(Opt, Opt%IndexInput%OutFiles(roRetroSSB)), &
      action = 'write', status =  'replace')
   write(cRetroSSBFile, "(A)") '#Retro SSB file   '   
   write(cRetroSSBFile, "(A)") "Run id: " // lrtrim(Opt%RunId)
   write(cRetroSSBFile, "(A)") 'One line contains: Iteration number and SSB over years'   
   close(cRetroSSBFile);
   open(cRetroRecruitFile, file = GetWorkFileName(Opt, Opt%IndexInput%OutFiles(roRetroRecruit)), &
      action = 'write', status =  'replace')
   write(cRetroRecruitFile, "(A)") '#Retro recruit file   '   
   write(cRetroRecruitFile, "(A)") "Run id: " // lrtrim(Opt%RunId)
   write(cRetroRecruitFile, "(A)") 'One line contains: Iteration number and recruit over years'   
   close(cRetroRecruitFile);
end subroutine OnInitiateRetro


subroutine OnRetroStart(Opt)
   ! Copy from boostrap data to observed data
   implicit none
   type(TOptimisation), intent(inout) :: Opt
   integer :: v, I
   character(len=256) :: oldInFile, oldOutFile
   type(TObservedData), pointer :: pVar
   integer :: Cat, iFleet, iYear, iAge, NFleets, NYears, NAges, PrevFlag, &
      DataLastYear
   type(TParamCube), pointer :: pParamCube
   type(TParamElm), pointer :: pParamElmLastYear, pParamElmPrevToLastYear, pParamElmLastCatchYear, pParamElmPrevToLastCatchYear
   
   ! Locally change, write and read observed data
   !Opt%RunningRetro = .true.
   do v = odFirst, odLast
      if (.not. associated(Opt%ObservedData(v)%Elm)) cycle
      do I = 0, size(Opt%ObservedData(v)%Elm) - 1
         pVar => Opt%ObservedData(v)%Elm(I)
         DataLastYear = pVar%FirstYear + pVar%NumYears - 1
         ! Special retrospective rule for the last data year:
         ! Preserve the intial -1 differences between last model-year and last data-year 
         ! through the retrospective process. This is done because "up-to-date" data sources 
         ! are not allways precent in the current intermediate model year.
         if (DataLastYear >= Opt%IndexInput%LastYear - 1) then
            pVar%NumYears = max(1, pVar%NumYears - 1)
         endif
      enddo
   enddo   
   !call WriteObsData(Opt)
   !call ReadObsData(Opt)
   !do v = odFirst, odLast
   !   call DeleteFile(GetDataFileName(Opt, lrtrim(Opt%IndexInput%DataFiles(v))))
   !enddo   
   !Opt%RunningRetro = .false.   
   
   ! Locally change, write and read parameters
   oldInFile = Opt%IndexInput%InParamFilename
   oldOutFile = Opt%IndexInput%OutFiles(roParamOut)
   Opt%IndexInput%OutFiles(roParamOut) = "ParamIn.retro" // lrtrim(inttostr(Opt%Loc%Stage)) // ".txt"
   Opt%IndexInput%InParamFilename = Opt%IndexInput%OutFiles(roParamOut)
   do Cat = cFirstCategory, cLastCategory
      pParamCube => Opt%ParamCubes(Cat)
      NFleets = size(pParamCube%Elm, 1)
      do iFleet = 0, NFleets - 1
         NYears = min(NumYears(Opt%IndexInput), size(pParamCube%Elm, 2))
         if (NYears < 3) cycle
         NAges = size(pParamCube%Elm, 3)
         do iAge = 0, NAges - 1
            pParamElmLastYear => GetParamElm(Opt, Cat, iFleet, NYears - 1, iAge, .false.)
            pParamElmPrevToLastYear => GetParamElm(Opt, Cat, iFleet, NYears - 2, iAge, .false.)
            pParamElmLastCatchYear => GetParamElm(Opt, Cat, iFleet, NumCatchYears(Opt%IndexInput) - 1, iAge, .false.)
            pParamElmPrevToLastCatchYear => GetParamElm(Opt, Cat, iFleet, NumCatchYears(Opt%IndexInput) - 2, iAge, .false.)
            select case(Cat)
               case(cNValues) 
                  pParamElmPrevToLastCatchYear%Flag = pParamElmLastCatchYear%Flag
                  pParamElmPrevToLastCatchYear%Value = pParamElmLastCatchYear%Value
                  pParamElmPrevToLastYear%Value = pParamElmLastYear%Value
            end select 
            pParamElmPrevToLastYear%Flag = pParamElmLastYear%Flag
         enddo
      enddo
   enddo
   Opt%IndexInput%LastYear = Opt%IndexInput%LastYear - 1
   Opt%IndexInput%LastCatchYear = Opt%IndexInput%LastCatchYear - 1
   call SaveParameters(Opt, .true.)
   if(.not.LoadParameters(Opt)) return
   Opt%IndexInput%InParamFilename = oldInFile
   Opt%IndexInput%OutFiles(roParamOut) = oldOutFile
   !call DeleteFile(Opt%IndexInput%InParamFilename)
   !call DeleteFile(Opt%IndexInput%OutFiles(roParamOut))
   
end subroutine OnRetroStart


subroutine OnRetroStop(Opt)
   implicit none
   type(TOptimisation), intent(inout) :: Opt
   character(len=256) :: oldOutFile, FileName
   integer :: iAge
   ! Stream out retro result
   call CalculateStockSummary(Opt)
   oldOutFile = Opt%IndexInput%OutFiles(roParamOut)
   FileName = Opt%IndexInput%OutFiles(roParamOut)
   if(Opt%Loc%Stage > 0) then
      FileName = "ParamOut.retro" // lrtrim(inttostr(Opt%Loc%Stage)) // ".txt"
      Opt%IndexInput%OutFiles(roParamOut) = lrtrim(FileName)
   endif
   call SaveParameters(Opt, .true.)
   Opt%IndexInput%OutFiles(roParamOut) = oldOutFile
   
   call SavePopulationModel(Opt)

   open(cRetroFMeanFile, file = GetWorkFileName(Opt, Opt%IndexInput%OutFiles(roRetroFMean)), &
      action = 'write', position =  'append')
   write(cRetroFMeanFile,'(I4, 1000f7.3)') Opt%IndexInput%LastYear, &
      Opt%PopModel%StockSummary(0 : NumYears(Opt%IndexInput) - 1, ssFMean);
   close(cRetroFMeanFile);

   open(cRetroSSBFile, file = GetWorkFileName(Opt, Opt%IndexInput%OutFiles(roRetroSSB)), &
      action = 'write', position =  'append')
   write(cRetroSSBFile,'(I4,1000f15.3)') Opt%IndexInput%LastYear, &
      Opt%PopModel%StockSummary(0 : NumYears(Opt%IndexInput) - 1, ssSSB)
   close(cRetroSSBFile)
   
   open(cRetroRecruitFile, file = GetWorkFileName(Opt, Opt%IndexInput%OutFiles(roRetroRecruit)), &
      action = 'write', position =  'append')
   write(cRetroRecruitFile,'(I4, 1000f15.3)') Opt%IndexInput%LastYear, &
      Opt%PopModel%StockSummary(0 : NumYears(Opt%IndexInput) - 1, ssRecruits)
   close(cRetroRecruitFile);
end subroutine OnRetroStop


end module Retro
